<?php

namespace app\common\middleware;

/**
 * Class UnDuplicate
 * @package app\common\middleware
 * 接口限流
 */
class RateLimiting
{
    // lua脚本，redis原子操作
    private $lua = <<<EOD
local api = ARGV[1]
local time = ARGV[2]
local limit = ARGV[3]
local keyPrefix = ARGV[4]
local key = keyPrefix..api..time
local current = redis.call('incr', key)
redis.call('expire', key,1)
local result = false
if(current<=tonumber(limit))
then
    result = true
end
return result
EOD;

    private $cachePrefix = 'RateLimiting:';

    public function handle($request, \Closure $next, $params=[])
    {
        if($this->isCanRateLimiting()){
            $api = str_replace('/', '', request()->baseUrl());
            $time = time();
            $limit = !empty($params['limit']) && is_int($params['limit']) ? $params['limit'] : 10;
            $limit <= 1 && $limit = 1;


            // 存储请求key
            $applyRequest = cache()->handler()->eval($this->lua,[$api,$time,$limit,$this->cachePrefix]);
            if (!$applyRequest) {
                exception('服务繁忙，请稍后再试');
            }
        }

        return $next($request);
    }

    /**
     * @return bool
     * 是否需要限制表单重复提交
     */
    public static function isCanRateLimiting()
    {
        return cache()->handler() instanceof \Redis;
    }
}